home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / ultracmd / ultracmd.c < prev   
Encoding:
C/C++ Source or Header  |  1991-02-12  |  21.4 KB  |  749 lines

  1. /* 
  2.  * ultracmd.c --
  3.  *
  4.  *    Program for dealing with the Ultranet VME adapter board..
  5.  *
  6.  * Copyright 1990 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /sprite/lib/forms/RCS/proto.c,v 1.3 90/01/12 12:03:36 douglis Exp $ SPRITE (Berkeley)";
  18. #endif /* not lint */
  19.  
  20. #include "sprite.h"
  21. #include "option.h"
  22. #include <stdio.h>
  23. #include <sys/file.h>
  24. #include <fs.h>
  25. #include "net.h"
  26. #include "netUltra.h"
  27. #include "/sprite/src/lib/include/dev/ultra.h"
  28. #include <status.h>
  29. #include <fmt.h>
  30.  
  31. /*
  32.  * The ucode file is in Intel format, which we don't have a constant for
  33.  * at the moment so borrow the VAX format.
  34.  */
  35.  
  36. #define UCODE_FORMAT    FMT_VAX_FORMAT
  37.  
  38. /*
  39.  * Variables settable via the command line.
  40.  */
  41.  
  42. Boolean    download = FALSE;    /* Download ucode to the adapter. */
  43. char    *dir = "/sprite/lib/ultra/ucode";  /* Directory containing ucode. */
  44. char    *file = NULL;        /* Ucode file to download. */
  45. Boolean reset = FALSE;        /* Reset the adapter. */
  46. Boolean getInfo = FALSE;    /* Get the adapter info. */
  47. char    *dev = "/dev";        /* Directory containing the device. */
  48. Boolean diag = FALSE;        /* Run diagnostic tests. */
  49. Boolean extDiag = FALSE;    /* Run extended diagnostic tests. */
  50. Boolean    external = FALSE;    /* Use external loopback when running
  51.                  * extended diagnostic tests. */
  52. char    *debug = NULL;        /* Set debugging output. */
  53. Boolean init = FALSE;        /* Send init command to adapter. */
  54. Boolean start = FALSE;        /* Send start command to the adapter. */
  55. char    *address = NULL;    /* Set adapter's Ultranet address. */
  56. char    *dsnd = NULL;        /* Send a datagram to the given host. */
  57. int    count = 1;        /* Number of times to send the datagram. */
  58. int    repeat = 1;        /* Number of times to repeat the send test.*/
  59. int    size = 0;        /* Size of the datagram to send. */
  60. char    *echo = NULL;        /* Host should echo datagrams back to
  61.                  * sender.  Use for receiver of dsnd option. */
  62. char    *trace = FALSE;        /* Set tracing of activity. */
  63. char    *source = FALSE;    /* Send a steady stream of datagrams to
  64.                  * the given host. */
  65. char    *sink = FALSE;        /* Toggle sink of incoming datagrams. */
  66. char    *stat = FALSE;        /* Manipulate collection of statistics. */
  67. int    map = -1;        /* Set mapping threshold. */
  68. int    bcopy = -1;        
  69. int    sg = -1;        
  70. Boolean hardReset = FALSE;
  71.  
  72. Option optionArray[] = {
  73.     {OPT_DOC, NULL, NULL, "Usage: ultracmd [options] [device]"},
  74.     {OPT_DOC, NULL, NULL, "Default device is \"ultra0\""},
  75.     {OPT_TRUE, "dl", (Address) &download,
  76.     "Download micro-code into the adapter"},
  77.     {OPT_STRING, "dir", (Address) &dir,
  78.     "Directory containing the micro-code files"},
  79.     {OPT_STRING, "f", (Address) &file,
  80.     "Micro-code file to download (default is to automatically pick one)"},
  81.     {OPT_TRUE, "r", (Address) &reset,
  82.     "Reset the adapter"},
  83.     {OPT_TRUE, "R", (Address) &hardReset,
  84.     "Hard reset the adapter"},
  85.     {OPT_TRUE, "t", (Address) &getInfo,
  86.     "Get type information from the adapter"},
  87.     {OPT_TRUE, "d", (Address) &diag,
  88.     "Run diagnostic tests on adapter"},
  89.     {OPT_TRUE, "ed", (Address) &extDiag,
  90.     "Run extended diagnostic tests on adapter"},
  91.     {OPT_TRUE, "ext", (Address) &external,
  92.     "Use external loopback when running extended diagnostics"},
  93.     {OPT_STRING, "dev", (Address) &dev,
  94.     "Directory containing the device"},
  95.     {OPT_STRING, "dbg", (Address) &debug,
  96.     "Ultranet device debugging output (on/off)"},
  97.     {OPT_TRUE, "i", (Address) &init,
  98.     "Send initialization command to adapter"},
  99.     {OPT_TRUE, "s", (Address) &start,
  100.     "Send start request to the adapter."},
  101.     {OPT_STRING, "a", (Address) &address,
  102.     "Set Ultranet address of adapter."},
  103.     {OPT_STRING, "dsnd", (Address) &dsnd,
  104.     "Send a datagram to the given address."},
  105.     {OPT_INT, "cnt", (Address) &count,
  106.     "Number of times to send a datagram (use with -dsnd)."},
  107.     {OPT_INT, "repeat", (Address) &repeat,
  108.     "Number of times to repeat the send-datagram test (use with -dsnd)."},
  109.     {OPT_INT, "size", (Address) &size,
  110.     "Size of the datagram (use with -dsnd)."},
  111.     {OPT_STRING, "echo", (Address) &echo,
  112.     "Echo received datagrams back to sender (on/off)"},
  113.     {OPT_STRING, "trace", (Address) &trace,
  114.     "Start and stop tracing of ultra driver activity (on/off)"},
  115.     {OPT_STRING, "source", (Address) &source,
  116.     "Send a stream of datagrams to the given address."},
  117.     {OPT_STRING, "sink", (Address) &sink,
  118.     "Toggle sink of incoming datagrams (on/off)"},
  119.     {OPT_STRING, "stat", (Address) &stat,
  120.     "Manipulate collection of ultranet statistics (on/off/clear/get)"},
  121.     {OPT_INT, "m", (Address) &map,
  122.     "Set mapping threshold."},
  123.     {OPT_INT, "bcopy", (Address) &bcopy,
  124.     "Bcopy test data size."},
  125.     {OPT_INT, "sg", (Address) &sg,
  126.     "SG bcopy test data size."},
  127. };
  128. int numOptions = sizeof(optionArray) / sizeof(Option);
  129.  
  130. /*
  131.  * The following are the names of the diagnostic tests as listed in the
  132.  * uvm man page provided in the Ultranet documentation.
  133.  */
  134. static char    *diagNames[] = {
  135.     "EPROM checksum",
  136.     "Abbreviated RAM check",
  137.     "Interrupt controller and interval timer",
  138.     "Internal loopback",
  139.     "FIFO RAM check",
  140.     "Checksum gate arrays",
  141.     "NMI control logic"
  142. };
  143. /*
  144.  * The following are the names of the extended diagnostic tests as
  145.  * listed in the uvm man page.
  146.  */
  147. static char    *extDiagNames[] = {
  148.     "EPROM checksum",
  149.     "Full RAM check",
  150.     "Interrupt controller and interval timer",
  151.     "Internal or external loopback",
  152.     "FIFO RAM check",
  153.     "Checksum gate arrays",
  154.     "NMI control logic",
  155.     "DMA to hosts memory using VME bus",
  156.     "Extended FIFO RAM check",
  157.     "FIFO Control logic"
  158. };
  159.  
  160. char    *myname;
  161. void    Download();
  162.  
  163. #define MIN(a,b) ((a) < (b) ? (a) : (b))
  164.  
  165. char    *device = "ultra0";
  166.  
  167.  
  168. /*
  169.  *----------------------------------------------------------------------
  170.  *
  171.  * main --
  172.  *
  173.  *    Parse the arguments and call the correct procedure.
  174.  *
  175.  * Results:
  176.  *    None.
  177.  *
  178.  * Side effects:
  179.  *    The state of the adapter board may be modified.
  180.  *
  181.  *----------------------------------------------------------------------
  182.  */
  183.  
  184. int
  185. main(argc, argv)
  186.     int        argc;
  187.     char    *argv[];
  188. {
  189.     int            argsLeft;
  190.     char        deviceName[FS_MAX_PATH_NAME_LENGTH];
  191.     int            fd;
  192.     ReturnStatus    status;
  193.  
  194.     myname = argv[0];
  195.     argsLeft = Opt_Parse(argc, argv, optionArray, numOptions, 0);
  196.     if (argsLeft > 2) {
  197.     Opt_PrintUsage(argv[0], optionArray, numOptions);
  198.     exit(1);
  199.     }
  200.     if (download + reset + getInfo + diag + extDiag + (debug != NULL) +
  201.     init + start + (address != NULL) + (dsnd != NULL) +
  202.     (echo != NULL) + (trace != NULL) + (source != NULL) +
  203.     (sink != NULL) + (stat != NULL) + (map >= 0) + hardReset > 1) {
  204.     printf("You can only specify one of the following options:\n");
  205.     printf("-dl, -r, -t, -d, -ed, -dbg, -i, -s, -a, -dsnd, -echo\n");
  206.     printf("-trace, -source, -stat, -m, -R\n");
  207.     Opt_PrintUsage(argv[0], optionArray, numOptions);
  208.     exit(1);
  209.     }
  210.     if ((external == TRUE) && (extDiag == FALSE)) {
  211.     printf("The -ext option can only be used with the -ed option\n");
  212.     Opt_PrintUsage(argv[0], optionArray, numOptions);
  213.     exit(1);
  214.     }
  215.     if (argsLeft == 2) {
  216.     device = argv[1];
  217.     }
  218.     sprintf(deviceName, "%s/%s", dev, device);
  219.     fd = open(deviceName, O_RDONLY);
  220.     if (fd < 0) {
  221.     printf("Can't open device \"%s\"\n", deviceName);
  222.     perror("");
  223.     Opt_PrintUsage(argv[0], optionArray, numOptions);
  224.     exit(1);
  225.     }
  226.     if (debug) {
  227.     int flag;
  228.     if (!strcasecmp(debug, "on")) {
  229.         flag = 1;
  230.     } else if (!strcasecmp(debug, "off")) {
  231.         flag = 0;
  232.     } else {
  233.         printf("Invalid parameter to -dbg. Must be \"on\" or \"off\"\n");
  234.         Opt_PrintUsage(argv[0], optionArray, numOptions);
  235.         exit(1);
  236.     }
  237.     status = Fs_IOControl(fd, IOC_ULTRA_DEBUG, sizeof(int), &flag, 0, 0);
  238.     if (status != SUCCESS) {
  239.         printf("Fs_IOControl returned 0x%x\n", status);
  240.     }
  241.     }
  242.     if (reset) {
  243.     status = Fs_IOControl(fd, IOC_ULTRA_RESET, 0, NULL, 0, 0);
  244.     if (status != SUCCESS) {
  245.         printf("Fs_IOControl returned 0x%x\n", status);
  246.     }
  247.     }
  248.     if (hardReset) {
  249.     status = Fs_IOControl(fd, IOC_ULTRA_HARD_RESET, 0, NULL, 0, 0);
  250.     if (status != SUCCESS) {
  251.         printf("Fs_IOControl returned 0x%x\n", status);
  252.     }
  253.     }
  254.     if (getInfo) {
  255.     Dev_UltraAdapterInfo    info;
  256.     status = Fs_IOControl(fd, IOC_ULTRA_GET_ADAP_INFO, 0, NULL, 
  257.             sizeof(Dev_UltraAdapterInfo), &info);
  258.     if (status != SUCCESS) {
  259.         printf("Fs_IOControl returned 0x%x\n", status);
  260.     } else {
  261.         printf(
  262.     "Model 99-%04d-%04d, Revision %d, Options %d, Firmware %d, Serial %d\n",
  263.         info.hwModel, info.hwVersion, info.hwRevision, 
  264.         info.hwOption, info.version, info.hwSerial);
  265.     }
  266.     }
  267.     if (diag) {
  268.     Dev_UltraDiag        cmd;
  269.     status = Fs_IOControl(fd, IOC_ULTRA_DIAG, 0, NULL, 
  270.             sizeof(Dev_UltraDiag), &cmd);
  271.     if (status != SUCCESS) {
  272.         printf("Fs_IOControl returned 0x%x\n", status);
  273.     } else {
  274.         if (cmd.error == 0) {
  275.         printf("All diagnostic tests passed.\n");
  276.         } else {
  277.         int    tmp = cmd.error;
  278.         int    i;
  279.         printf("The following diagnostic tests failed:\n");
  280.         for (i = 0; i < sizeof(int); i++) {
  281.             if (tmp & 1) {
  282.             printf("%2d: %s\n", i+1, diagNames[i]);
  283.             }
  284.             tmp >>= 1;
  285.         }
  286.         }
  287.     }
  288.     }
  289.     if (extDiag) {
  290.     Dev_UltraExtendedDiag    cmd;
  291.     cmd.externalLoopback = external;
  292.     status = Fs_IOControl(fd, IOC_ULTRA_EXTENDED_DIAG, sizeof(cmd), 
  293.             (Address) &cmd, sizeof(cmd), (Address) &cmd);
  294.     if (status != SUCCESS) {
  295.         printf("Fs_IOControl returned 0x%x\n", status);
  296.     } else {
  297.         if (cmd.error == 0) {
  298.         printf("All extended diagnostic tests passed.\n");
  299.         } else {
  300.         int    tmp = cmd.error;
  301.         int    i;
  302.         printf("The following extended diagnostic tests failed:\n");
  303.         for (i = 0; i < sizeof(int); i++) {
  304.             if (tmp & 1) {
  305.             printf("%2d: %s\n", i+1, extDiagNames[i]);
  306.             }
  307.             tmp >>= 1;
  308.         }
  309.         }
  310.     }
  311.     }
  312.     if (download) {
  313.     Download(fd, dir, file);
  314.     }
  315.     if (init) {
  316.     status = Fs_IOControl(fd, IOC_ULTRA_INIT, 0, NULL, 0, NULL);
  317.     if (status != SUCCESS) {
  318.         printf("Fs_IOControl returned 0x%x\n", status);
  319.     } 
  320.     }
  321.     if (start) {
  322.     status = Fs_IOControl(fd, IOC_ULTRA_START, 0, NULL, 0, NULL);
  323.     if (status != SUCCESS) {
  324.         printf("Fs_IOControl returned 0x%x\n", status);
  325.     } 
  326.     }
  327.     if (address) {
  328.     Net_UltraAddress    ultraAddress;
  329.     int            count;
  330.     int            group;
  331.     int            unit;
  332.     count = sscanf(address,"%d/%d", &group, &unit);
  333.     if (count != 2) {
  334.         printf("%s: argument to -a is of form <group>/<unit>\n", myname);
  335.         Opt_PrintUsage(argv[0], optionArray, numOptions);
  336.         exit(1);
  337.     }
  338.     if (group < 1 || group > 1000) {
  339.         printf("%s: group must be 1-1000\n", myname);
  340.         Opt_PrintUsage(argv[0], optionArray, numOptions);
  341.         exit(1);
  342.     }
  343.     if (unit < 32 || unit > 62) {
  344.         printf("%s: unit must be 32-62\n", myname);
  345.         Opt_PrintUsage(argv[0], optionArray, numOptions);
  346.         exit(1);
  347.     }
  348.     Net_UltraAddressSet(&ultraAddress, group, unit);
  349.     status = Fs_IOControl(fd, IOC_ULTRA_ADDRESS, sizeof(Net_UltraAddress),
  350.             &ultraAddress, 0, NULL);
  351.     if (status != SUCCESS) {
  352.         printf("Fs_IOControl returned 0x%x\n", status);
  353.     } 
  354.     }
  355.     if (dsnd) {
  356.     Dev_UltraSendDgram    dgram;
  357.     int            pid;
  358.     int            n;
  359.     int            group;
  360.     int            unit;
  361.     n = sscanf(dsnd,"%d/%d", &group, &unit);
  362.     if (n != 2) {
  363.         printf("%s: argument to -dsnd is of form <group>/<unit>\n", myname);
  364.         Opt_PrintUsage(argv[0], optionArray, numOptions);
  365.         exit(1);
  366.     }
  367.     if (group < 1 || group > 1000) {
  368.         printf("%s: group must be 1-1000\n", myname);
  369.         Opt_PrintUsage(argv[0], optionArray, numOptions);
  370.         exit(1);
  371.     }
  372.     if (unit < 32 || unit > 62) {
  373.         printf("%s: unit must be 32-62\n", myname);
  374.         Opt_PrintUsage(argv[0], optionArray, numOptions);
  375.         exit(1);
  376.     }
  377.     Net_UltraAddressSet(&dgram.address.ultra, group, unit);
  378.     dgram.count = count;
  379.     dgram.size = size;
  380.     dgram.useBuffer = FALSE;
  381.     while (repeat > 0) {
  382.         repeat--;
  383.         status = Fs_IOControl(fd, IOC_ULTRA_SEND_DGRAM, 
  384.             sizeof(dgram), &dgram, sizeof(dgram), &dgram);
  385.         if (status != SUCCESS) {
  386.         printf("Fs_IOControl returned 0x%x\n", status);
  387.         break;
  388.         }
  389.         Time_Divide(dgram.time, count, &dgram.time);
  390.         printf("%d\t%d.%06d\n", size, dgram.time.seconds, 
  391.         dgram.time.microseconds);
  392.     }
  393.     }
  394.     if (echo) {
  395.     Dev_UltraEcho        echoParam;
  396.     if (!strcasecmp(echo, "on")) {
  397.         echoParam.echo = TRUE;
  398.     } else if (!strcasecmp(echo, "off")) {
  399.         echoParam.echo = FALSE;
  400.     } else {
  401.         printf("Invalid parameter to -echo. Must be \"on\" or \"off\"\n");
  402.         Opt_PrintUsage(argv[0], optionArray, numOptions);
  403.         exit(1);
  404.     }
  405.     status = Fs_IOControl(fd, IOC_ULTRA_ECHO, sizeof(echoParam),
  406.         &echoParam, 0, NULL);
  407.     if (status != SUCCESS) {
  408.         printf("Fs_IOControl returned 0x%x\n", status);
  409.     }
  410.     }
  411.     if (trace) {
  412.     int flag;
  413.     if (!strcasecmp(trace, "on")) {
  414.         flag = 1;
  415.     } else if (!strcasecmp(trace, "off")) {
  416.         flag = 0;
  417.     } else {
  418.         printf("Invalid parameter to -trace. Must be \"on\" or \"off\"\n");
  419.         Opt_PrintUsage(argv[0], optionArray, numOptions);
  420.         exit(1);
  421.     }
  422.     status = Fs_IOControl(fd, IOC_ULTRA_TRACE, sizeof(int), &flag, 0, 0);
  423.     if (status != SUCCESS) {
  424.         printf("Fs_IOControl returned 0x%x\n", status);
  425.     }
  426.     }
  427.     if (source) {
  428.     Dev_UltraSendDgram    dgram;
  429.     int            pid;
  430.     int            n;
  431.     int            group;
  432.     int            unit;
  433.     n = sscanf(source,"%d/%d", &group, &unit);
  434.     if (n != 2) {
  435.         printf("%s: argument to -dsnd is of form <group>/<unit>\n", myname);
  436.         Opt_PrintUsage(argv[0], optionArray, numOptions);
  437.         exit(1);
  438.     }
  439.     if (group < 1 || group > 1000) {
  440.         printf("%s: group must be 1-1000\n", myname);
  441.         Opt_PrintUsage(argv[0], optionArray, numOptions);
  442.         exit(1);
  443.     }
  444.     if (unit < 32 || unit > 62) {
  445.         printf("%s: unit must be 32-62\n", myname);
  446.         Opt_PrintUsage(argv[0], optionArray, numOptions);
  447.         exit(1);
  448.     }
  449.     Net_UltraAddressSet(&dgram.address.ultra, group, unit);
  450.     dgram.count = count;
  451.     dgram.size = size;
  452.     dgram.useBuffer = FALSE;
  453.     while (repeat > 0) {
  454.         repeat--;
  455.         status = Fs_IOControl(fd, IOC_ULTRA_SOURCE, 
  456.             sizeof(dgram), &dgram, sizeof(dgram), &dgram);
  457.         if (status != SUCCESS) {
  458.         printf("Fs_IOControl returned 0x%x\n", status);
  459.         break;
  460.         }
  461.         printf("%d\t%d.%06d\n", size, dgram.time.seconds, 
  462.         dgram.time.microseconds);
  463.     }
  464.     }
  465.     if (sink) {
  466.     Dev_UltraSink        sinkParam;
  467.     int flag;
  468.     int packets;
  469.     if (!strcasecmp(sink, "on")) {
  470.         flag = 1;
  471.     } else if (!strcasecmp(sink, "off")) {
  472.         flag = 0;
  473.     } else {
  474.         printf("Invalid parameter to -sink. Must be \"on\" or \"off\"\n");
  475.         Opt_PrintUsage(argv[0], optionArray, numOptions);
  476.         exit(1);
  477.     }
  478.     status = Fs_IOControl(fd, IOC_ULTRA_SINK, sizeof(int), &flag, 
  479.             sizeof(sinkParam), &sinkParam);
  480.     if (status != SUCCESS) {
  481.         printf("Fs_IOControl returned 0x%x\n", status);
  482.     } else {
  483.         printf("%d packets sunk\n", sinkParam.packets);
  484.     }
  485.     }
  486.     if (stat) {
  487.     Dev_UltraStats        statParam;
  488.     int            ioctl;
  489.     int            flag;
  490.     int            i;
  491.     if (!strcasecmp(stat, "on")) {
  492.         flag = 1;
  493.         ioctl = IOC_ULTRA_COLLECT_STATS;
  494.     } else if (!strcasecmp(stat, "off")) {
  495.         flag = 0;
  496.         ioctl = IOC_ULTRA_COLLECT_STATS;
  497.     } else if (!strcasecmp(stat, "clear")) {
  498.         ioctl = IOC_ULTRA_CLEAR_STATS;
  499.     } else if (!strcasecmp(stat, "get")) {
  500.         ioctl = IOC_ULTRA_GET_STATS;
  501.     } else {
  502.         printf("Invalid parameter to -stat.\n");
  503.         printf("Must be \"on\",\"off\",\"clear\", or \"get\"\n");
  504.         Opt_PrintUsage(argv[0], optionArray, numOptions);
  505.         exit(1);
  506.     }
  507.     switch(ioctl) {
  508.         case IOC_ULTRA_COLLECT_STATS:
  509.         status = Fs_IOControl(fd, ioctl, sizeof(int), &flag, 0,0);
  510.         break;
  511.         case IOC_ULTRA_CLEAR_STATS:
  512.         status = Fs_IOControl(fd, ioctl, 0,0,0,0);
  513.         break;
  514.         case IOC_ULTRA_GET_STATS:
  515.         status = Fs_IOControl(fd, ioctl, 0, 0, 
  516.                 sizeof(statParam), &statParam);
  517.         break;
  518.     }
  519.     if (status != SUCCESS) {
  520.         printf("Fs_IOControl returned 0x%x\n", status);
  521.     } else {
  522.         switch(ioctl) {
  523.         case IOC_ULTRA_COLLECT_STATS:
  524.             break;
  525.         case IOC_ULTRA_CLEAR_STATS:
  526.             break;
  527.         case IOC_ULTRA_GET_STATS:
  528.             printf("Packets sent:\t%9d\n", statParam.packetsSent);
  529.             printf("Bytes sent  :\t%9d\n", statParam.bytesSent);
  530.             printf("Histogram of packets sent:\n");
  531.             for (i = 0; i < 33; i++) {
  532.             printf("[%2d,%2d):\t%9d\n", i, i+1, 
  533.                 statParam.sentHistogram[i]);
  534.             }
  535.             printf("Packets received:\t%9d\n", 
  536.                 statParam.packetsReceived);
  537.             printf("Bytes received  :\t%9d\n", 
  538.                 statParam.bytesReceived);
  539.             printf("Histogram of packets received:\n");
  540.             for (i = 0; i < 33; i++) {
  541.             printf("[%2d,%2d):\t%9d\n", i, i+1, 
  542.                 statParam.receivedHistogram[i]);
  543.             }
  544.             break;
  545.         }
  546.     }
  547.     }
  548.     if (map >= 0) {
  549.     status = Fs_IOControl(fd, IOC_ULTRA_MAP_THRESHOLD, sizeof(int), &map, 
  550.             0, 0);
  551.     if (status != SUCCESS) {
  552.         printf("Fs_IOControl returned 0x%x\n", status);
  553.     } 
  554.     }
  555.     if (bcopy >= 0) {
  556.     Time    time;
  557.     status = Fs_IOControl(fd, IOC_ULTRA_BCOPY_TEST, sizeof(int), &bcopy, 
  558.             sizeof(Time), &time);
  559.     if (status != SUCCESS) {
  560.         printf("Fs_IOControl returned 0x%x\n", status);
  561.     } else {
  562.         printf("%d\t%d.%06d\n", bcopy, time.seconds, 
  563.         time.microseconds);
  564.     }
  565.     }
  566.     if (sg >= 0) {
  567.     Time    time;
  568.     status = Fs_IOControl(fd, IOC_ULTRA_SG_BCOPY_TEST, sizeof(int), &sg, 
  569.             sizeof(Time), &time);
  570.     if (status != SUCCESS) {
  571.         printf("Fs_IOControl returned 0x%x\n", status);
  572.     } else {
  573.         printf("%d\t%d.%06d\n", sg, time.seconds, 
  574.         time.microseconds);
  575.     }
  576.     }
  577.     close(fd);
  578.     if (status != SUCCESS) {
  579.     exit(1);
  580.     }
  581.     exit(0);
  582. }
  583.  
  584. /*
  585.  *----------------------------------------------------------------------
  586.  *
  587.  * Download --
  588.  *
  589.  *    Downloads the Ultranet adapter ucode onto the board..
  590.  *
  591.  * Results:
  592.  *    None.
  593.  *
  594.  * Side effects:
  595.  *    The ucode is loaded onto the board.
  596.  *
  597.  *----------------------------------------------------------------------
  598.  */
  599.  
  600. void
  601. Download(devFD, dir, file)
  602.     int        devFD;        /* Handle on the ultranet adapter. */
  603.     char    *dir;        /* Name of directory containing ucode files.*/
  604.     char    *file;        /* If non-NULL then name of the file to
  605.                  * download. */
  606. {
  607.     int        fd;
  608.     char    path[FS_MAX_PATH_NAME_LENGTH];
  609.     int        bytesRead;
  610.     struct    {
  611.     unsigned long    unused;
  612.     unsigned long    length;
  613.     unsigned long    address;
  614.     } header;
  615.     char buffer[0x8000];    /* Biggest possible size of data. */
  616.     Dev_UltraLoad    loadCmd;
  617.     Dev_UltraGo        goCmd;
  618.     ReturnStatus    status;
  619.     int            fmtStatus;
  620.     int            inSize;
  621.     int            outSize;
  622.     int            startAddress;
  623.     int            bytesSent;
  624.     int            address;
  625.  
  626.     if (file == NULL) {
  627.     Dev_UltraAdapterInfo    info;
  628.     status = Fs_IOControl(devFD, IOC_ULTRA_GET_ADAP_INFO, 0, NULL, 
  629.             sizeof(Dev_UltraAdapterInfo), &info);
  630.     if (status != SUCCESS) {
  631.         if (status == DEV_BUSY) {
  632.         printf("You must reset the adapter first.\n");
  633.         exit(1);
  634.         }
  635.         printf("%s: Fs_IOControl to get adapter info failed 0x%x.\n", 
  636.         myname, status);
  637.         exit(1);
  638.     }
  639.     sprintf(path,"%s/uvm%d.ult", dir, info.hwModel);
  640.     } else {
  641.     sprintf(path,"%s/%s", dir, file);
  642.     }
  643.     fd = open(path, O_RDONLY);
  644.     if (fd < 0) {
  645.     printf("%s: could not open ucode file \"%s\"\n", myname, path);
  646.     perror(NULL);
  647.     }
  648.     bytesRead = read(fd, buffer, sizeof(header));
  649.     while(bytesRead > 0) {
  650.     /*
  651.      * The load address is stored in the ucode file in 
  652.      * Intel byte order.
  653.      */
  654.     inSize = sizeof(buffer);
  655.     outSize = sizeof(int);
  656.     fmtStatus = Fmt_Convert("w", UCODE_FORMAT, &inSize, 
  657.             (Address) &buffer[8], FMT_MY_FORMAT, &outSize,
  658.             (Address) &header.address);
  659.     if (fmtStatus != 0) {
  660.         printf("%s: Fmt_Convert of header returned %d\n", myname,
  661.         fmtStatus);
  662.         exit(1);
  663.     }
  664.     if (outSize != sizeof(int)) {
  665.         printf("%s: header changed size after conversion.\n", myname);
  666.         exit(1);
  667.     }
  668.     /*
  669.      * The length field is stored in sun byte order.
  670.      */
  671.     inSize = sizeof(buffer);
  672.     outSize = sizeof(int);
  673.     fmtStatus = Fmt_Convert("w", FMT_68K_FORMAT, &inSize, 
  674.             (Address) &buffer[4], FMT_MY_FORMAT, &outSize,
  675.             (Address) &header.length);
  676.     if (fmtStatus != 0) {
  677.         printf("%s: Fmt_Convert of header returned %d\n", myname,
  678.         fmtStatus);
  679.         exit(1);
  680.     }
  681.     if (outSize != sizeof(int)) {
  682.         printf("%s: header changed size after conversion.\n", myname);
  683.         exit(1);
  684.     }
  685.     /*
  686.      * If the length field is 0 then the address field contains the 
  687.      * start address.
  688.      */
  689.     if (header.length == 0) {
  690.         startAddress = header.address;
  691.         break;
  692.     }
  693. #if 0
  694.     printf("Header address = 0x%x\n", header.address);
  695.     printf("Header length = %d 0x%x\n", header.length, header.length);
  696. #endif
  697.     /* 
  698.      * Break the data into pieces that can be sent via an ioctl and
  699.      * send it to the device.
  700.      */
  701.     bytesSent = 0;
  702.     address = header.address;
  703.     while(bytesSent < bytesRead) {
  704.         int     length;
  705.  
  706.         length = MIN(header.length - bytesSent, sizeof(loadCmd.data));
  707.         loadCmd.address = address;
  708.         loadCmd.length = length;
  709.         /*
  710.          * Now read in the data.
  711.          */
  712.         bytesRead = read(fd, loadCmd.data, length);
  713.         if (bytesRead != length) {
  714.         printf("%s: short read on data, %d expecting %d\n", myname,
  715.             bytesRead, length);
  716.         exit(1);
  717.         }
  718. #if 0
  719.         printf("Download 0x%x 0x%x\n", loadCmd.address, loadCmd.length);
  720. #endif
  721.         status = Fs_IOControl(devFD, IOC_ULTRA_LOAD, sizeof(loadCmd), 
  722.             (Address) &loadCmd, 0, NULL);
  723.         if (status != SUCCESS) {
  724.         printf("Fs_IOControl returned 0x%x\n", status);
  725.         exit(1);
  726.         }
  727.         bytesSent += length;
  728.         /*
  729.          * Now adjust the load address in case we are sending a
  730.          * block of data in multiple ioctls.
  731.          */
  732.         address += length;
  733.     }
  734.     bytesRead = read(fd, buffer, sizeof(header));
  735.     }
  736.     /*
  737.      * Now send the start address.
  738.      */
  739.     goCmd.address = startAddress;
  740.     status = Fs_IOControl(devFD, IOC_ULTRA_GO, sizeof(goCmd), 
  741.         (Address) &goCmd, 0, NULL);
  742.     if (status != SUCCESS) {
  743.     printf("Fs_IOControl returned 0x%x\n", status);
  744.     exit(1);
  745.     }
  746. }
  747.  
  748.  
  749.